package siec;

import siec.Connection;
import siec.GameEvent;

public class ConnectionListener extends Thread {

	private static final int USER_COUNT = 2;

	private Server server;

	private boolean canJoinToGame = false;

	private int clientsCount = 0;

	private int joinedClientsCount = 0;

	private int readyClientsCount = 0;

        // rozsyła wiadomość czy mogą się połączyć
	private void canJoinToGame(boolean b) {
		canJoinToGame = b;
		GameEvent geOut;
		if (canJoinToGame) {
			geOut = new GameEvent(GameEvent.SB_CAN_JOIN_GAME);
                        server.zegarSerwer.increment();
                        server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                        server.zapis.println("CAN_JOIN_GAME");     
                        server.zapis.println();                        
                        
		} else {
			geOut = new GameEvent(GameEvent.SB_CANNOT_JOIN_GAME);
                        
                        server.zegarSerwer.increment();
                        server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                        server.zapis.println("CANNOT_JOIN_GAME");     
                        server.zapis.println();
		}
		sendBroadcastMessage(geOut);
	}

        // po otrzymaniu komunikatu, startuje gre
	private void startGame() {
		readyClientsCount = 0;
		GameEvent geOut;
		geOut = new GameEvent(GameEvent.SB_START_GAME);
                
                server.zegarSerwer.increment();
                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                server.zapis.println("START_GAME");     
                server.zapis.println();
            
		int count = 1;

		for (Connection connection : server.getConnections()) {
			if (connection.isAlive() && connection.isJoined()) {
				geOut.setMessage(Integer.toString(count));
				sendMessage(connection, geOut);
				count++;
			}
		}
	}

	public ConnectionListener(Server server) {
		this.server = server;
	}

        @Override
	public void run() {
		while (server.isRunning()) { //pętla, dopóki serwer działa
			for (int i = server.getConnections().size() - 1; i >= 0; --i) {
				Connection connection = (Connection) server.getConnections()
						.get(i);

				if (!connection.isAlive()) {
					if (!"".equals(connection.getNick())) {
						GameEvent geOut;
						geOut = new GameEvent(GameEvent.SB_PLAYER_QUIT); /** Klient zakończył grę */
                                                server.zegarSerwer.increment();
                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                server.zapis.println("PLAYER_QUIT");     
                                                server.zapis.println();
						sendBroadcastMessage(geOut);
						clientsCount--;
						joinedClientsCount = 0;
						//canJoinToGame(false);
					}
					connection.close();
					server.getConnections().remove(connection);
				} else {
					GameEvent ge;
					while ((ge = receiveMessage(connection)) != null) {
						switch (ge.getType()) { //odpowiedzi
						case GameEvent.C_CHAT_MSG: /** Klient wysyła wiadomość tekstową */
							if (!"".equals(ge.getPlayerId())) {
								GameEvent geOut;
								geOut = new GameEvent(GameEvent.SB_CHAT_MSG, ge
										.getMessage());
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("CHAT_MSG");     
                                                                server.zapis.println();
								geOut.setPlayerId(ge.getPlayerId());
								sendBroadcastMessage(geOut);
							}
							break;
						case GameEvent.C_LOGIN:/** Próba zalogowania przez klienta */
							if (!"".equals(ge.getPlayerId())) {
								if (clientsCount == USER_COUNT) { // w grze jest już 2 graczy
									GameEvent geOut;
									geOut = new GameEvent(
											GameEvent.S_LOGIN_FAIL,
											"W grze znajduje się już dwóch graczy!");
									sendMessage(connection, geOut);
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("LOGIN_FAIL");     
                                                                server.zapis.println();

									geOut = new GameEvent(
											GameEvent.S_TOO_MANY_CONNECTIONS);
									sendMessage(connection, geOut);
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("TOO_MANY_CONNECTIONS");     
                                                                server.zapis.println();                                                                        
								} else if (isPlayerIDUnique(ge.getPlayerId())) {
									connection.setNick(ge.getPlayerId());
									GameEvent geOut;
									geOut = new GameEvent(GameEvent.SB_LOGIN,
											ge.getPlayerId()); //przyłączył się klient
									sendBroadcastMessage(geOut);
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("LOGIN");     
                                                                server.zapis.println();                                                                        
									clientsCount++;
									if (clientsCount == USER_COUNT) {
										canJoinToGame(true);
									}
								} /*else {
									GameEvent geOut;
									geOut = new GameEvent(
											GameEvent.S_LOGIN_FAIL,
											"Użytkownik \"" + ge.getPlayerId()
													+ "\" już istnieje");
									sendMessage(connection, geOut);
									geOut = new GameEvent(
											GameEvent.S_USER_EXIST);
									sendMessage(connection, geOut);
								}*/
							}
							break;
						case GameEvent.C_JOIN_GAME:
							if (!"".equals(connection.getNick())) {
								if (clientsCount != USER_COUNT) {
									GameEvent geOut;
									geOut = new GameEvent(
											GameEvent.S_JOIN_GAME_FAIL);
									sendMessage(connection, geOut);
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("JOIN_GAME_FAIL");     
                                                                server.zapis.println();                                                                        
								} else {
									connection.setJoined(true);
									GameEvent geOut;
									geOut = new GameEvent(
											GameEvent.S_JOIN_GAME_OK);
									sendMessage(connection, geOut);
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("JOIN_GAME_OK");     
                                                                server.zapis.println();                                                                        
									geOut = new GameEvent(
											GameEvent.SB_PLAYER_JOINED, ge
													.getPlayerId());
									sendBroadcastMessage(geOut);
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("PLAYER_JOINED");     
                                                                server.zapis.println();
									joinedClientsCount++;
									if (joinedClientsCount == USER_COUNT) {
										startGame();
									}
								}
							}
							break;
/*						case GameEvent.C_READY:
							if (!"".equals(connection.getNick())) {
								readyClientsCount++;
								if (readyClientsCount == USER_COUNT) {
									GameEvent geOut;
									geOut = new GameEvent(
											GameEvent.SB_ALL_READY);
									sendBroadcastMessage(geOut);
								}
							}
							break;
*/
						case GameEvent.C_SHOT:
							if (!"".equals(ge.getPlayerId())) {
								GameEvent geOut;
								geOut = new GameEvent(GameEvent.SB_SHOT, ge
										.getMessage());
								geOut.setPlayerId(ge.getPlayerId());
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("SHOT");     
                                                                server.zapis.println();                                                                
								sendBroadcastMessage(geOut);
							}
							break;
						case GameEvent.C_SHOT_RESULT:
							if (!"".equals(ge.getPlayerId())) {
								GameEvent geOut;
								geOut = new GameEvent(GameEvent.SB_SHOT_RESULT,
										ge.getMessage());
								geOut.setPlayerId(ge.getPlayerId());
                                                                sendBroadcastMessage(geOut);
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("SHOT_RESULT");     
                                                                server.zapis.println();            
								GameEvent geOut2;
								geOut2 = new GameEvent(GameEvent.ZEGAR);
								geOut2.setPlayerId(ge.getPlayerId());    
                                                                geOut2.setMessage(Integer.toString(server.zegarSerwer.getLocalMax()));                
								sendBroadcastMessage(geOut2);
							}
							break;

						case GameEvent.C_QUIT_GAME:
								joinedClientsCount = 0;
                                                                server.zegarSerwer.increment();
                                                                server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                                server.zapis.println("QUIT_GAME");     
                                                                server.zapis.println();                                                                
							break;
                                                    
                                                case GameEvent.ZEGAR:
                                                    System.out.println("OTRZYMAŁEM TĄ WIADOMOŚĆ OD KLIENTA!! Teraz zwiększę zagar o: ");
                                                    server.zegarSerwer.increment();
                                                    server.zapis.println("Zegar: " + server.zegarSerwer.getLocalMax());
                                                    server.zapis.println("ZWIĘKSZAM ZEGAR OD KLIENTA");     
                                                    server.zapis.println(); 
                                                    
                                                    server.zegarSerwer.setClock(1, Integer.valueOf(ge.getMessage()) );
                                                    break; 
                            
						}
					}
				}
			}

			try {
				Thread.sleep(50);
			} catch (Exception ex) {
			}
		}
	}

        //wyslanie wiadomosci
	public void sendMessage(Connection connection, GameEvent ge) {
		connection.sendMessage(ge.toSend());
	}

        //wysłanie wiadomości do wszystkich klientow
	public void sendBroadcastMessage(GameEvent ge) {
            for (Connection connection : server.getConnections()) {
                if (connection.isAlive()) {
                        sendMessage(connection, ge);
                }
            }
	}

        //odbiór wiadomości
	public GameEvent receiveMessage(Connection connection) {
		if (connection.messagesQueue.isEmpty()) {
			return null;
		} else {
			GameEvent ge = new GameEvent((String) connection.messagesQueue
					.getFirst());
			connection.messagesQueue.removeFirst();
			return ge;
		}
	}

	public boolean isPlayerIDUnique(String nick) {
            for (Connection connection : server.getConnections()) {
                if (connection.getNick().compareTo(nick) == 0)
                        return false;
            }
		return true;
	}

}
